import itertools, os, re
import pyrem_strs.originedstr as rm

# python-graph (http://code.google.com/p/python-graph/), ver. 1.6.3
from pygraph.classes.graph import graph as pg_graph 
from pygraph.readwrite.dot import write as pg_write

# read source files from current directory
fileTable = rm.FileTable()
fileTable.read_from_directory("", re.compile(".+[.]py$"), recursive=True)
initFiles = [fileTable.pop(p) for p in fileTable.keys() if p.endswith("__init__.py")]

# find identifiers
s = r'[ruRU]*"(\\.|[^"])*"|"""((!?""").)*"""'
pat = re.compile("|".join([r"\b(?P<def>(def|class)\s+)?(?P<id>[a-zA-Z_]\w*)", # identifier
        s, s.replace('"', "'"), r"#[^\n]*\n"])) # string literals, comment
referredIds, definedIds = [], []
for _, ns in sorted(fileTable.iteritems()):
    for m in pat.finditer(rm.origined_str(ns)):
        id = m.group('id')
        if m.group('def'): definedIds.append(id)
        elif id: referredIds.append(id)
referredIds = filter(set(definedIds).__contains__, referredIds)

# build graph of coupling (by identifiers) between the source files
graph = pg_graph()
graph.add_nodes(ns.name for ns in fileTable.values())
for defName, defs in itertools.groupby(sorted(definedIds)):
    defs = list(defs)
    refs = [id for id in referredIds if id == defName]
    defFiles = [id.origin0.namedstr for id in defs]
    refFiles = [id.origin0.namedstr for id in referredIds if id == defName]
    if not set(refFiles) - set(defFiles): continue # skip if the id is used only in one file
    files = sorted(set(defFiles + refFiles))
    for edge in itertools.combinations((f.name for f in files), 2):
        if not graph.has_edge(edge): graph.add_edge(edge)

# draw the graph
for ns in fileTable.values():
    for attr in ("shape", "box"), ("label", ns.name.replace(os.path.sep, "/\\n")):
        graph.add_node_attribute(ns.name, attr)
file("graph.dot", "w").write(pg_write(graph))